package com.youkeda.app.service.impl;

import com.youkeda.app.dao.UserDao;
import com.youkeda.app.dataobject.UserDO;
import com.youkeda.app.model.PersonalRecord;
import com.youkeda.app.model.Result;
import com.youkeda.app.model.User;
import com.youkeda.app.service.MatchDataService;
import com.youkeda.app.service.PersonalRecordService;
import com.youkeda.app.service.UserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @ClassName UserServiceImpl
 * @Author 刘正星
 * @Date 2020/8/26 8:17
 **/
@Service
public class UserServiceImpl implements UserService {


    @Autowired
    private UserDao userDAO;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private PersonalRecordService personalRecordService;
    @Autowired
    private MatchDataService matchDataService;

    private static final Logger LOG = LoggerFactory.getLogger(UserServiceImpl.class);


    @Autowired
    private JavaMailSender javaMailSender;
    @Value("${sendEmailAddress}")
    private String sendEmailAddress;

    @Override
    public Result<Boolean> add(UserDO userDO) {
        Result result = new Result();
        result.setData(true);
        result.setSuccess(true);
        if (userDO == null) {
            result.setData(false);
            result.setSuccess(false);
            return result;
        }
        if (StringUtils.isEmpty(userDO.getMobile())) {
            result.setMessage("邮箱不能为空");
            result.setData(false);
            return result;
        }
        if (StringUtils.isEmpty(userDO.getPassword())) {
            result.setData(false);
            result.setMessage("密码不能为空！");
        }

        //每次先去redis校验
        String email = (String) redisTemplate.opsForValue().get(userDO.getMobile());
        //当redis没有数据的时候再去数据库查询
        if (StringUtils.isEmpty(email)) {
            //redis缓存没有，为了安全起见
            UserDO user = userDAO.selectByEmail(userDO.getMobile());
            if (user != null) {
                result.setMessage("邮箱已被注册");
                result.setData(false);
                return result;
            }
        }
        //将手机号缓存到redis里(键是邮箱，值是密码)
        redisTemplate.opsForValue().set(userDO.getMobile(), userDO.getPassword());
        //随机六位验证码
        String code = String.valueOf((int) (Math.random() * 9 + 1) * 100000);
        //存入redis 设置过期时间60s
        redisTemplate.opsForValue().set("code", code, 60, TimeUnit.SECONDS);
        SimpleMailMessage message = new SimpleMailMessage();
        //发送验证码
        message.setFrom(sendEmailAddress);
        message.setTo(userDO.getMobile());
        message.setSubject("验证码");
        message.setText("验证码" + code);
        javaMailSender.send(message);
        //这里不做验证码校验了


        int row = userDAO.insert(userDO);
        if (row != 1) {
            result.setMessage("插入失败");
            result.setData(false);
            return result;
        }
        return result;
    }

    @Override
    public Result<Boolean> login(String email, String password) {
        Result result = new Result();
        result.setData(true);
        result.setSuccess(true);

        if (StringUtils.isEmpty(email) || StringUtils.isEmpty(password)) {
            result.setData(false);
            result.setMessage("邮箱或密码不能为空！");
            return result;
        }
        //先去redis校验
        String pwd = (String) redisTemplate.opsForValue().get(email);
        //如果redis没有则去数据库校验
        if (StringUtils.isEmpty(pwd)) {
            //根据邮箱去数据库查询
            UserDO userDO = userDAO.selectByEmail(email);
            //判断有没有该用户，也将该邮箱缓存到redis中，并且设置过期时间
            redisTemplate.opsForValue().set(email, "", 1000, TimeUnit.SECONDS);
            if (userDO == null) {
                result.setMessage("邮箱未注册");
                result.setData(false);
                return result;
            }
            //将查询到的结果缓存到redis
            redisTemplate.opsForValue().set(email, userDO.getPassword());
            //判断密码是否正确
            if (!userDO.getPassword().equals(password)) {
                result.setMessage("密码不正确");
                result.setData(false);
                return result;
            }

            result.setData(true);
            result.setMessage("登录成功");
            return result;
        } else {
            //能查到则根据redis校验
            if (pwd.equals(password)) {
                result.setMessage("登录成功");
                result.setData(true);
                return result;
            }
            result.setData(true);
            result.setMessage("密码不正确");
            return result;
        }
    }

    @Override
    public Integer save(User user) {
        int success = 0;
        if (user == null) {
            LOG.error("user ==null");
            return success;
        }
        UserDO userDO = new UserDO(user);
        if (user.getId() == null) {
            int insert = userDAO.insert(userDO);
            if (insert <= 0) {
                LOG.error("insert <= 0");
                return success;
            }
            //创建用户时默认创建个人战绩
            //创建用户时 默认会创建个人战绩
            PersonalRecord personalRecord = new PersonalRecord();
            personalRecord.setWinTimes(0);
            personalRecord.setTopTenTimes(0);
            personalRecord.setEliminateNum(0);
            personalRecord.setPlayNum(0);
            personalRecord.setPoints(1200);
            personalRecord.setKd(0d);
            personalRecord.setUserId(userDO.getId());
            success = personalRecordService.save(personalRecord);
            //初始化该用户的缓存信息
            redisTemplate.opsForZSet().add("integralRankUser",userDO.getId(),personalRecord.getPoints());
            //将个人信息存储到hash
            User redisUser = new User();
            redisUser.setNickname(user.getNickname());
            redisUser.setAvatar(user.getAvatar());
            redisTemplate.opsForHash().put("integralRankUser",userDO.getId(),redisUser);
        }else {
            if (user.getValid() ==0){
                personalRecordService.delete(user.getId());
                matchDataService.delete(user.getId());
            }

            int insert = userDAO.updateByPrimaryKey(userDO);
            if (insert < 0){
                return success;
            }
            success = insert;
        }
        return success;
    }

    @Override
    public User get(Long id) {

        if (id == null) {
            return null;
        }

        UserDO userDO = userDAO.selectByPrimaryKey(id);
        System.out.println("userDO: "+userDO.toString());

        if (userDO == null) {
            return null;
        }
        return userDO.convertToModel();
    }

    @Override
    public List<User> getByIds(List<Long> ids) {
        if (CollectionUtils.isEmpty(ids) || ids == null){
            return null;
        }
        List<User> users = userDAO.selectByIds(ids).stream().map(userDO -> userDO.convertToModel()).collect(Collectors.toList());
        if (users ==null || CollectionUtils.isEmpty(users)){
            return  null;
        }

        return users;
    }
}
